"""
Pydantic 异常处理
"""

from dataclasses import dataclass
from typing import (
    Any,
    Dict,
    List,
    Type,
    Union,
)

from pydantic_x.errors import (
    PydanticErrorBase,
    get_code_2_error,
)
from pydantic_x.parser import parse_model_fields


def pydantic_exception_handler(exc, model) -> "ErrorWrapper":
    """ Pydantic 异常处理 """

    code_2_error: Dict[str, Type[PydanticErrorBase]] = get_code_2_error()
    field_dic: Dict[str, str] = {}
    error_list: List[ErrorDict] = []

    if model:
        parse_model_fields(model, field_dic)

    for error in exc.errors():
        error_dict = ErrorDict(**error)
        msg_template_zh: str = code_2_error.get(error_dict.code) or error_dict.msg
        error_dict.msg_zh = msg_template_zh.format(**error_dict.ctx)
        error_dict.field_zh = field_dic.get(error_dict.field) or error_dict.field
        error_list.append(error_dict)

    return ErrorWrapper(error_list)


class ErrorDict:
    """ 异常字典 """

    LOC_CONNECTOR: str = "."
    """ 异常位置字段连接符 """

    def __init__(self, **kwargs) -> None:
        self.field_raw: List[Union[str, int]] = list(kwargs["loc"])
        """ 异常位置字段信息 """

        self.msg: str = kwargs["msg"]
        """ 异常消息 """

        self.code: str = kwargs["type"]
        """ 异常类型 """

        self.ctx: Dict[str, Any] = kwargs["ctx"]
        """ 异常上下文信息 """

        # ---------- 以下为扩展字段（后续会被覆盖） ----------
        self.field_zh: str = self.field
        """ 异常位置信息（中文） """

        self.msg_zh: str = self.msg
        """ 异常消息（中文） """

    @property
    def field(self) -> str:
        """ 异常位置信息 """

        return self.LOC_CONNECTOR.join(map(str, self.field_raw))

    def dict(self, full: bool = False) -> Dict[str, Any]:
        if not full:
            return {
                "code": self.code,
                "field_zh": self.field_zh,
                "msg_zh": self.msg_zh,
            }

        return {
            "code": self.code,
            "field": self.field,
            "field_zh": self.field_zh,
            "field_raw": self.field_raw,
            "msg": self.msg,
            "msg_zh": self.msg_zh,
        }


@dataclass
class ErrorWrapper:
    """ 异常包装器 """

    error_list: List[ErrorDict]
    """ 异常信息列表 """

    @property
    def complete_info(self) -> List[Dict[str, Any]]:
        """ 完整的异常信息列表 """

        return [
            error.dict(full=True)
            for error in self.error_list
        ]

    @property
    def simple_info(self) -> List[Dict[str, Any]]:
        """ 简单的异常信息列表 """

        return [
            error.dict()
            for error in self.error_list
        ]

    @property
    def string(self) -> str:
        """ 简单的异常信息 """

        return "\n".join(
            f"{error.field_zh} {error.msg_zh}"
            for error in self.error_list
        )
